package com.kjlink.internal.workreport.stats.service;

import cn.xuqiudong.common.base.service.BaseService;
import com.kjlink.internal.workreport.base.enums.ProjectTimeStatsCategory;
import com.kjlink.internal.workreport.helper.ReportCommonHelper;
import com.kjlink.internal.workreport.project.model.Project;
import com.kjlink.internal.workreport.project.service.ProjectService;
import com.kjlink.internal.workreport.report.service.WorkReportService;
import com.kjlink.internal.workreport.stats.lookup.ProjectMonthLookup;
import com.kjlink.internal.workreport.stats.lookup.UserWeekLookup;
import com.kjlink.internal.workreport.stats.mapper.ProjectTimeStatsMapper;
import com.kjlink.internal.workreport.stats.model.ProjectTimeStats;
import com.kjlink.internal.workreport.stats.vo.EchartsBarVo;
import com.kjlink.internal.workreport.stats.vo.EchartsSimpleLineVo;
import com.kjlink.internal.workreport.stats.vo.SerieVo;
import com.kjlink.internal.workreport.stats.vo.UserReportTimeVo;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 功能: :项目工时统计 Service
 *
 * @author Vic.xu
 * @since 2024-05-27 10:11
 */
@Service
public class ProjectTimeStatsService extends BaseService<ProjectTimeStatsMapper, ProjectTimeStats> {

    @Resource
    private ProjectService projectService;

    @Resource
    private WorkReportService workReportService;

    @Override
    protected boolean hasAttachment() {
        return false;
    }

    public ProjectTimeStats findOne(ProjectTimeStats entity) {
        return mapper.findOne(entity);
    }

    /**
     * 项目工时概览
     */
    public EchartsBarVo overview(Project lookup, int year, int month) {
        EchartsBarVo echartsBarVo = new EchartsBarVo();
        List<Project> list = projectService.list(lookup);
        if (CollectionUtils.isEmpty(list)) {
            return echartsBarVo;
        }
        int monthDate = ReportCommonHelper.toMonthDate(year, month);
        List<String> legendData = Stream.of(month + "月工时", year + "年工时", "总工时").collect(Collectors.toList());
        //1 设置统计维度
        echartsBarVo.setLegendData(legendData);

        //3.1 总工时
        SerieVo totalSerie = new SerieVo("总工时", "bar");

        List<String> projectNames = list.stream().map(project -> {
            totalSerie.addData(project.getUsedTime());
            return project.getName();
        }).collect(Collectors.toList());
        //2 设置x轴
        echartsBarVo.setxAxisData(projectNames);
        List<Integer> projectIds = list.stream().map(Project::getId).collect(Collectors.toList());

        //3.2 当月工时
        SerieVo monthSerie = new SerieVo(month + "月工时", "bar");
        //3.3 当年工时
        SerieVo yearSerie = new SerieVo(year + "年工时", "bar");
        Map<Integer, ProjectTimeStats> monthUsedTime = getUsedTime(ReportCommonHelper.toMonthDate(year, month), ProjectTimeStatsCategory.month);
        Map<Integer, ProjectTimeStats> yearUsedTime = getUsedTime(year, ProjectTimeStatsCategory.year);
        projectIds.forEach(id -> {
            ProjectTimeStats mstats = monthUsedTime.get(id);
            monthSerie.addData(mstats == null ? 0 : mstats.getTotal());
            ProjectTimeStats ystats = yearUsedTime.get(id);
            yearSerie.addData(ystats == null ? 0 : ystats.getTotal());
        });
        echartsBarVo.addSerie(monthSerie);
        echartsBarVo.addSerie(yearSerie);
        echartsBarVo.addSerie(totalSerie);


        return echartsBarVo;
    }

    public Map<Integer, ProjectTimeStats> getUsedTime(int date, ProjectTimeStatsCategory category) {
        ProjectTimeStats entity = new ProjectTimeStats();
        entity.setCategory(category);
        entity.setDate(date);
        List<ProjectTimeStats> list = this.list(entity);
        return Optional.ofNullable(list).orElse(new ArrayList<>()).stream()
                .collect(Collectors.toMap(ProjectTimeStats::getProjectId, t -> t, (k1, k2) -> k1));
    }

    /**
     * 项目月度工时折线图
     *
     * @param lookup
     * @return
     */
    public EchartsSimpleLineVo monthLine(ProjectMonthLookup lookup) {
        List<ProjectTimeStats> list = mapper.monthLines(lookup);
        EchartsSimpleLineVo result = new EchartsSimpleLineVo();
        list.forEach(stats -> {
            result.addxAxisData(String.valueOf(stats.getDate()));
            result.addSeriesData(stats.getTotal());
        });
        return result;
    }

    /**
     * 周工时统计
     *
     * @param lookup
     * @return
     */
    public EchartsSimpleLineVo weekBar(UserWeekLookup lookup) {
        List<UserReportTimeVo> weekTimes = workReportService.weekTimeStats(lookup);
        EchartsSimpleLineVo result = new EchartsSimpleLineVo();
        // 使用流进行分组和累计操作
        Map<String, List<UserReportTimeVo>> groupedByUserName = weekTimes.stream()
                .collect(Collectors.groupingBy(UserReportTimeVo::getUserName));

        List<UserReportTimeVo> collect = weekTimes.stream()
                // 按照 userName 分组
                .collect(Collectors.groupingBy(UserReportTimeVo::getUserName,
                        // 累计 total
                        Collectors.summingInt(UserReportTimeVo::getTotal)))
                .entrySet().stream()
                .map(entry -> {
                    String userName = entry.getKey();
                    int total = entry.getValue();
                    return new UserReportTimeVo(userName, total);
                    // 按 total 从高到低排序
                }).sorted(Comparator.comparingInt(UserReportTimeVo::getTotal).reversed())
                .collect(Collectors.toList());

        collect.forEach(timeVo -> {
            result.addxAxisData(timeVo.getUserName());
            result.addSeriesData(timeVo.getTotal());
            StringBuilder otherInfo = new StringBuilder();
            groupedByUserName.get(timeVo.getUserName()).forEach(vo -> {
                otherInfo.append(vo.getProjectName()).append(":").append(ReportCommonHelper.toHoursNumber(vo.getTotal())).append("小时").append("<br/>");
            });
            result.addOtherInfo(otherInfo.toString());
        });


        return result;

    }
}
